const gulp = require('gulp');
const pug = require('gulp-pug');
const babel = require('gulp-babel');
const babelConfig = require('./babel.config');
const rename = require('gulp-rename');
const inject = require('gulp-inject');
const less = require('gulp-less');
const browserSync = require('browser-sync').create();
const fs = require('fs');
const path = require('path');
const { args, fileExists, readFilesContent, deleteDirectoryRecursive } = require('./functions.js');
const crypto = require('crypto');
const replace = require('gulp-replace');
const gulp_clean = require('gulp-clean');
 
function randomSuffix() {
  return crypto.randomBytes(4).toString('hex').slice(0, 8);
}
// Function to load mock data
function loadMockData(templateName) {
    try {
        const data = require(path.join(__dirname, 'src', 'components', templateName, 'mock.js'));
        return data;
    } catch (err) {
        console.warn(`Error loading mock data for template ${templateName}:`, err);
        return {};
    }
}

// Compile pug files
function compilePug() {
    const templateName = args().com; // 获取命令行中传入的模板名
    if (!templateName) {
        console.error('Please provide a template name.');
        process.exit(1);
    }

    const mockData = loadMockData(templateName);

    return gulp.src(`src/components/${templateName}/*.pug`)
        .pipe(pug({ locals: mockData }))
        .pipe(rename('index.html'))
        .pipe(gulp.dest(`src/components/${templateName}/dist/.`))
        .pipe(browserSync.stream());
}

function compileJs(){
    const templateName = args().com; // 获取命令行中传入的模板名

    return gulp.src([`src/components/${templateName}/*.ts`,`src/components/${templateName}/enter.js`])
    .pipe(babel(babelConfig))
    .pipe(rename(function(path){
        path.basename = `index-bundle-${randomSuffix()}`
    }))
    .pipe(gulp.dest(`dist/${templateName}`))
}

function compileCss(){
    const templateName = args().com; // 获取命令行中传入的模板名

    return gulp.src([`src/components/${templateName}/*.less`,`src/components/${templateName}/*.css`])
    .pipe(less())
    .pipe(rename(function(path){
        path.basename = `style-bundle-${randomSuffix()}`
    }))
    .pipe(gulp.dest(`dist/${templateName}/.`))
    .pipe(browserSync.stream());
}

function cleanDist(){
    return new Promise(( res, rej)=>{
        const templateName = args().com; // 获取命令行中传入的模板名
        deleteDirectoryRecursive(path.join('dist', templateName))
        deleteDirectoryRecursive(path.join(`src/components/${templateName}/`,'dist'))
        res()
    })
}

function cleanStyles(){
    return new Promise(( res, rej)=>{
        const templateName = args().com; // 获取命令行中传入的模板名
        deleteDirectoryRecursive(path.join('dist', templateName), '.css')
        res()
    })
}

function cleanJs(){
    return new Promise(( res, rej)=>{
        const templateName = args().com; // 获取命令行中传入的模板名
        deleteDirectoryRecursive(path.join('dist', templateName), '.js')
        res()
    })
}

function cleanHtml(){
    return new Promise(( res, rej)=>{
        const templateName = args().com; // 获取命令行中传入的模板名
        deleteDirectoryRecursive(path.join(`src/components/${templateName}/`, 'dist'), '.html')
        res()
    })
}

// 插入编译后的脚本到 index.html
function injectScripts() {
    const templateName = args().com; // 获取命令行中传入的模板名

    const injectSrc = gulp.src([path.join('dist', templateName, '**/*.js')], { read: false });
    const injectOptions = {
      starttag: '<!-- inject:js -->',
      endtag: '<!-- endinject -->',
      transform: (filepath, file) => '<script src="' + filepath.split("/").slice(3).join('/') + '"></script>'
    };

    const injectCss = gulp.src([path.join('dist', templateName, '**/*.css')], { read: false });
    const injectCssOptions = {
      starttag: '<!-- inject:css -->',
      endtag: '<!-- endinject -->',
      transform: (filepath, file) => `<link rel="stylesheet" href="${filepath.split("/").slice(3).join('/')}" media="all">` //'<link src="' + filepath + '"></script>'
    };

    return gulp.src(path.join('public', 'index.html'))
      .pipe(inject(injectSrc, injectOptions))
      .pipe(inject(injectCss, injectCssOptions))
      .pipe(replace('<!-- inject:content:html -->', function() {
        const arr = readFilesContent(path.join(`src/components/${templateName}/`,'dist'), '.html') 
        return arr.join('\n');
      }))
      .pipe(rename({ dirname: '' }))
      .pipe(gulp.dest(`dist/${templateName}`,{ overwrite: true }));
      
}

function reload(done){
    browserSync.reload(done)
    console.log(done)
}

// Watch files and serve with BrowserSync
function serve() {
    const templateName = args().com;

    browserSync.init({
        server: `./dist/${templateName}`
    });

    gulp.watch(`src/components/${templateName}/*.pug`, gulp.series(cleanHtml, compilePug, injectScripts));
    gulp.watch(`src/components/${templateName}/**/*.js`, gulp.series(cleanJs, compileJs, injectScripts));
    gulp.watch([`src/components/${templateName}/**/*.less`,`src/components/${templateName}/**/*.css`], gulp.series(cleanStyles, compileCss, injectScripts));
    gulp.watch(`dist/${templateName}/**/*.html`).on('change', reload);
}

module.exports.dev = gulp.series( cleanDist, compilePug, compileCss, compileJs, injectScripts, serve);
module.exports.injectScripts = injectScripts